package plugin.demo

import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.fileEditor.OpenFileDescriptor
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import com.intellij.psi.search.FilenameIndex
import com.intellij.psi.search.GlobalSearchScope
import java.util.function.Consumer
import java.util.regex.Pattern
import java.util.stream.Collectors

data class FileInfo(
    val project: Project,
    val virtualFile: VirtualFile,
    val offset: Int = 0,
    val fileName: String,
    val canonicalPath: String
) {

    override fun toString(): String {
        return "FileInfo{" +
                "project=" + project +
                ", virtualFile=" + virtualFile +
                ", offset=" + offset +
                ", fileName='" + fileName + '\'' +
                ", canonicalPath='" + canonicalPath + '\'' +
                '}'
    }
}


class GetSelectText : AnAction() {
    override fun getActionUpdateThread(): ActionUpdateThread {
        return ActionUpdateThread.BGT
    }

    override fun actionPerformed(event: AnActionEvent) {
        try {

            val editor = event.getData(LangDataKeys.EDITOR)
            val project = event.getData(CommonDataKeys.PROJECT)

//        val module = event.getData(LangDataKeys.MODULE)
            if (project != null && editor != null) {
                val document = editor.document
                val fileDocumentManager = FileDocumentManager.getInstance()
                val selectionModel = editor.selectionModel
                val start = selectionModel.selectionStart
                val end = selectionModel.selectionEnd
                val range = TextRange(start, end)
                //获取选中字符
                val selectTxt = document.getText(range)

                if (StringUtil.isNotEmpty(selectTxt)) {
                    val map: MutableMap<String, FileInfo> = HashMap()
                    val currentFile = fileDocumentManager.getFile(document)
                    val goFiles = findGoFile(project, /*module,*/ selectTxt, currentFile!!.name)
                    goFiles.forEach(
                        Consumer { goFile ->
                            val virtualFile = goFile!!.virtualFile
                            val offset = goFile.text.indexOf("\"" + selectTxt + "\"")
                            val fileInfo = FileInfo(project, virtualFile, offset, virtualFile.name, goFile.name)

                            val keys =
                                virtualFile.canonicalPath!!.split("/".toRegex()).dropLastWhile { it.isEmpty() }
                                    .toTypedArray()
                            val key = keys[keys.size - 2] + "/" + keys[keys.size - 1]
                            map[key] = fileInfo
                        }
                    )
                    usingUI(map, editor)
                }
            }
        } catch (_: Exception) {
//    截获所有异常
        }
    }

    /**
     * 找到对应的 go文件
     */
    private fun findGoFile(
        project: Project,/* module: Module?,*/
        router: String,
        currentFileName: String
    ): List<PsiFile?> {
//        val moduleScope = GlobalSearchScope.moduleScope(
//            module!!
//        )
        // FilenameIndex.getFilesByName(project, "", moduleScope);
        val psiFiles = ArrayList<PsiFile?>()
        val virtualFiles = FilenameIndex.getAllFilesByExt(project, "go", GlobalSearchScope.projectScope(project))
        //        System.out.println("查找到的文件数量:" + virtualFiles.size());
        for (virtualFile in virtualFiles) {
            //            System.out.println("1.文件 " + virtualFile + "\n2.文件名 " + virtualFile.getName());

            val psiManager = PsiManager.getInstance(project)
            val file = psiManager.findFile(virtualFile)
            val text = file!!.text
            if (text != null) {
                // 首次如果全匹配, 直接返回
                // 没匹配的话先暂存起来
                if (text.contains(router)) {
                    val fileName = file.name
                    val regex = "consts\\.ValidatorPrefix\\s{0,100}\\+\\s{0,100}\"$router\""
                    val r = Pattern.compile(regex)
                    val matcher = r.matcher(text)
                    if (currentFileName == "api.go" || currentFileName == "web.go") {
                        //设置查找范围
                        if (fileName == "api_register_validator.go" || fileName == "web_register_validator.go") {
                            if (matcher.find()) {
                                psiFiles.add(file)
                            }
                        }
                    } else if (currentFileName == "api_register_validator.go" || currentFileName == "web_register_validator.go") {
                        //设置查找范围
                        if (fileName == "api.go" || fileName == "web.go") {
                            if (matcher.find()) {
                                psiFiles.add(file)
                            }
                        }
                    }
                }
            }
        }

        // 其他过滤匹配
        return psiFiles
    }

    /**
     * 触发条件
     */
    override fun update(e: AnActionEvent) {
        //Get required data keys
        val project = e.project
        val editor = e.getData(CommonDataKeys.EDITOR)
        //Set visibility only in case of existing project and editor and if some text in the editor is selected
        e.presentation.isVisible = project != null && editor != null && editor.selectionModel.hasSelection()
    }

    companion object {
        /**
         * 加载UI
         *
         * @param
         */
        fun usingUI(fileInfoMap: Map<String, FileInfo>, editor: Editor?) {
            val list = fileInfoMap.entries.stream()
                .map { e: Map.Entry<String, FileInfo> -> e.value.fileName + "     " + e.key }
                .collect(
                    Collectors.toList()
                )
            val instance = JBPopupFactory.getInstance() // 创建实例
            val popupChooserBuilder = instance.createPopupChooserBuilder(list)
            popupChooserBuilder.setItemChosenCallback { s ->

                // 添加监听事件
                val fileInfo = fileInfoMap[s.split(" {5}".toRegex()).dropLastWhile { it.isEmpty() }
                    .toTypedArray()[1]]
                if (fileInfo != null) {
                    OpenFileDescriptor(
                        fileInfo.project,
                        fileInfo.virtualFile,
                        fileInfo.offset
                    ).navigate(true)
                    //                    System.out.println("FileInfo:" + fileInfo);
                } /*else {
                    //                    System.out.println("空的");
                }*/

            }

            val popup = popupChooserBuilder.createPopup()
            popup.showInBestPositionFor(editor!!)
        }
    }
}
